home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Your Choice 3
/
Your Choice Software Collection 3.iso
/
prgmming
/
xlib41
/
easyx.asm
< prev
next >
Wrap
Assembly Source File
|
1994-03-23
|
14KB
|
339 lines
.MODEL LARGE,PASCAL
.386P
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;TASM Modifications
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;TASM users should set TASMMODE below to TRUE.
TRUE EQU 1
FALSE EQU 0
TASMMODE = FALSE
IF TASMMODE
MASM51
QUIRKS
NOJUMPS
PUSHW MACRO IMMEDIATE16:REST ;PUSH imm16 (for TASM compatibility)
IF (@WordSize EQ 4)
DB 66H
ENDIF
DB 68H
DW IMMEDIATE16
ENDM
PUSHD MACRO IMMEDIATE32:REST ;PUSH imm32 (for TASM compatibility)
IF (@WordSize EQ 2)
DB 66H
ENDIF
DB 68H
DD IMMEDIATE32
ENDM
INCLUDE XLIBB.INC
ELSE
ARG TEXTEQU <>
OPTION PROC:PRIVATE
OPTION NOLJMP
INCLUDE XLIB.INC
ENDIF
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;DSEG declaration. The DSEG data segment has combine type 'FAR_DATA' when
;being used in a Borland library. Under most memory models, Borland places all
;segments with combine type 'DATA' in DGROUP. Unfortunately, the offsets seen
;by the library in such segments may have a different base than those seen by C.
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
IF TASMMODE
DSEG SEGMENT PARA PUBLIC USE16 'FAR_DATA'
ELSE
DSEG SEGMENT PARA PUBLIC USE16 'DATA'
ENDIF
ASSUME DS:DSEG
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;Stacks used for MOVMEM routine. Stacks are dynamically allocated to cover the
;possibility that MOVMEM is called both within the main thread of execution and
;in interrupt handlers. The possibility of nested interrupts is also covered.
;Calls to MOVMEM may be nested four deep. Each dynamically allocated stack
;contains 100H bytes.
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ALIGN 8
DB 800H DUP(0) ;Sufficient space for four stacks
ISTKPTR DD OFFSET $ ;Initial stack pointer (dynamically adjusted)
STKALLOC EQU 200H ;Number of bytes allocated per stack for MOVMEM
DSEG ENDS
CSEG SEGMENT PARA PUBLIC USE16 'CODE'
ASSUME CS:CSEG
IF TASMMODE
SMALLSTACK
ENDIF
;Allocate extended memory block. Error code returned in DX:AX. Arguments are:
;NOBYTES:DWORD = Number of bytes to allocate
;ADRPTR:DWORD = Far pointer to linear address of allocated block
;SIZEPTR:DWORD = Far pointer to size of allocated block
;HANDLEPTR:DWORD = Far pointer to handle of allocated block
XMALLOC PROC FAR,
ARG NOBYTES:DWORD,ADRPTR:DWORD,SIZEPTR:DWORD,HANDLEPTR:DWORD ;Number of bytes to allocate
PUSH EBX
PUSH ECX
PUSH DS
MOV EAX,NOBYTES
CALL GETMEM
OR EAX,EAX
JNZ SHORT EXIT
PUSH EBX
LDS BX,ADRPTR
MOV [BX],EDX
LDS BX,SIZEPTR
MOV [BX],ECX
LDS BX,HANDLEPTR
POP DWORD PTR [BX]
EXIT: PUSH EAX ;Return error code in DX:AX
POP AX
POP DX
POP DS
POP ECX
POP EBX
RET
XMALLOC ENDP
;Release extended memory block. Error code returned in DX:AX. Arguments are:
;HANDLE:DWORD = Handle to previously allocated block
XFREE PROC FAR,
ARG HANDLE:DWORD ;Handle to previously allocated block
MOV EAX,HANDLE
CALL FREEMEM
PUSH EAX ;Put error code in DX:AX
POP AX
POP DX
RET
XFREE ENDP
;Map physical memory to logical address space. Error code returned in DX:AX.
;Arguments are:
;PHYSADR:DWORD = Linear address of physical memory
;BLKSIZE:DWORD = Size of memory block (in bytes)
;LOGADRPTR:DWORD = Far pointer to DWORD to receive logical address
MAPIOMEM PROC FAR,
ARG PHYSADR:DWORD,BLKSIZE:DWORD,LOGADRPTR:DWORD
PUSH BX
PUSH DS
MOV EDX,PHYSADR
MOV EAX,BLKSIZE
PUSHD OFFSET PMMAPIO
CALL CALLPM
LDS BX,LOGADRPTR
MOV [BX],EDX
PUSH EAX ;Place error code in DX:AX
POP AX
POP DX
POP DS
POP BX
RET
MAPIOMEM ENDP
;Move memory. This routine is suitable for interrupt handlers. It uses a
;stack in DSEG rather than TSEG. Arguments are:
;DESTADR:DWORD = Destination address.
;SOURCEADR:DWORD = Source address.
;NOBYTES:DWORD = Number of bytes to transfer.
ALIGN 16
MOVMEM PROC FAR,
ARG DESTADR:DWORD,SOURCEADR:DWORD,NOBYTES:DWORD
PUSHAD
PUSH DS
PUSH ES
PUSH FS
PUSH GS
MOV AX,DSEG
MOV DS,AX
MOV ESI,SOURCEADR ;Load registers as required by MOVMEM32
MOV EDI,DESTADR
MOV ECX,NOBYTES
MOV EDX,ISTKPTR ;Get currently available pointer for the dynamic stack
SUB ISTKPTR,STKALLOC ;Prepare dynamic stack for possibility of interrupt call back to this routine
MOV BX,SP ;Save the old stack in EBX
PUSH SS
PUSH BX
POP EBX
MOV SS,AX ;Load the dynamic stack
MOV ESP,EDX
CALL SWITCHPM ;Switch to 16-bit protected mode
PUSHW 0H ;PUSH 32-bit far return address back to this procedure
MOV AX,CSEGSEL
PUSH AX
PUSHD OFFSET RETADR
PUSHW 0H ;PUSH 32-bit far address of MOVMEM32
MOV AX,TSEGSEL
PUSH AX
PUSHD OFFSET MOVMEM32
MOV DS,FLATDSEL ;Switch to flat data model
DB 66H ;Execute 32-bit RETF
RETF
RETADR: CALL SWITCHRM ;Switch back to real mode
PUSH EBX ;Load calling stack
LSS SP,[ESP]
ADD ISTKPTR,STKALLOC ;Adjust dynamic stack pointer
POP GS
POP FS
POP ES
POP DS
POPAD
RET
MOVMEM ENDP
;Calculate linear address from segment address. Call with segment address on
;stack. Linear address returned in DX:AX.
LINADR PROC FAR,
ARG SEGADDRESS:DWORD ;Segment address of variable
MOV AX,WORD PTR SEGADDRESS[2] ;Do not corrupt high words (might be used in 16-bit interrupt handler)
XOR DX,DX
SHLD DX,AX,4
SHL AX,4
ADD AX,WORD PTR SEGADDRESS[0]
ADC DX,0
RET
LINADR ENDP
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;Interfaces to XLIB file management routines. Each of these procedures should
;be called with the segment address of the control block on the stack. These
;routines cannot be called during interrupts since each routine calls DOS.
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;Create file.
XFCREATE PROC FAR
PUSHD OFFSET PMXCREATE
JMP CHAINTOPM
XFCREATE ENDP
;Open file.
XFOPEN PROC FAR
PUSHD OFFSET PMXOPEN
JMP CHAINTOPM
XFOPEN ENDP
;Close file.
XFCLOSE PROC FAR
PUSHD OFFSET PMXCLOSE
JMP CHAINTOPM
XFCLOSE ENDP
;Load file
XFLOAD PROC FAR
PUSHD OFFSET PMXLOAD
JMP CHAINTOPM
XFLOAD ENDP
;Save file.
XFSAVE PROC FAR
PUSHD OFFSET PMXSAVE
JMP CHAINTOPM
XFSAVE ENDP
;Random read file.
XFREAD PROC FAR
PUSHD OFFSET PMXREAD
JMP CHAINTOPM
XFREAD ENDP
;Random write file.
XFWRITE PROC FAR
PUSHD OFFSET PMXWRITE
JMP CHAINTOPM
XFWRITE ENDP
;Transfer control to protected mode after converting segment address of control
;block to linear address in EAX.
CHAINTOPM PROC FAR
PUSH DWORD PTR [ESP+8] ;PUSH segment address of control block
CALL LINADR
PUSH DX
PUSH AX
POP EAX
CALL CALLPM
RET 4
CHAINTOPM ENDP
PUBLIC PASCAL XMALLOC
PUBLIC PASCAL XFREE
PUBLIC PASCAL MAPIOMEM
PUBLIC PASCAL LINADR
PUBLIC PASCAL MOVMEM
PUBLIC PASCAL XFCREATE
PUBLIC PASCAL XFOPEN
PUBLIC PASCAL XFCLOSE
PUBLIC PASCAL XFLOAD
PUBLIC PASCAL XFSAVE
PUBLIC PASCAL XFREAD
PUBLIC PASCAL XFWRITE
CSEG ENDS
TSEG SEGMENT PARA PUBLIC USE32 'CODE'
ASSUME CS:TSEG
IF TASMMODE
LARGESTACK
ENDIF
;Transfer memory. Call with source address in ESI, destination address in EDI,
;and number of bytes to transfer in ECX. Does not preserve registers. This
;routine is far and is therefore a departure from XLIB policy. This approach
;is used because the routine is not entered with the standard XLIB mode switch
;procedures, CALLPM and ENTERPM. Standard mode switch procedures are not used
;because they are not reentrant and therefore cannot be used in interrupt
;handlers.
ALIGN 16
MOVMEM32 PROC FAR
CMP EDI,ESI
JBE ENTERDN4
JMP ENTERUP4
ALIGN 4
UP4LOOP: MOV EAX,[ESI+1*ECX] ;Destination address is higher than source address
MOV [EDI+1*ECX],EAX
ENTERUP4: SUB ECX,4
JAE UP4LOOP
ADD ECX,4
JNZ ENTERUP1
RET
ALIGN 4
UP1LOOP: MOV AL,[ESI+1*ECX]
MOV [EDI+1*ECX],AL
ENTERUP1: DEC ECX
JNS UP1LOOP
RET
ALIGN 4
DN4LOOP: MOV EAX,[ESI] ;Destination address is lower than source address
MOV [EDI],EAX
ADD ESI,4
ADD EDI,4
ENTERDN4: SUB ECX,4
JAE DN4LOOP
ADD ECX,4
JNZ ENTERDN1
RET
ALIGN 4
DN1LOOP: MOV AL,[ESI]
MOV [EDI],AL
INC ESI
INC EDI
ENTERDN1: DEC ECX
JNS DN1LOOP
RET
MOVMEM32 ENDP
TSEG ENDS
END